/*
 * @Author: wushengran
 * @Date: 2024-06-04 13:58:28
 * @Description: 
 * 
 * Copyright (c) 2024 by atguigu, All Rights Reserved. 
 */
#include "tim4.h"

#define MODE_INPUT                        0
#define MODE_OUTPUT_SPEED_10MHZ           1
#define MODE_OUTPUT_SPEED_2MHZ            2
#define MODE_OUTPUT_SPEED_50MHZ           3

#define CONF_OUTPUT_GENERAL_PUSH_PULL     0
#define CONF_OUTPUT_GENERAL_OPEN_DRAIN    1
#define CONF_OUTPUT_ALTERNATE_PUSH_PULL   2
#define CONF_OUTPUT_ALTERNATE_OPEN_DRAIN  3

#define CONF_INPUT_ANALOG                 0
#define CONF_INPUT_FLOATING               1
#define CONF_INPUT_PULL_UP_DOWN           2
#define CONF_INPUT_RESERVED               3

void TIM4_Init(void)
{
    // 1. 开启时钟
    RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
    RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;

    // 2. GPIO工作模式，PB6：输入 CNF-01，MODE-00
    GPIOB->CRL &= ~(0xF << (6 * 4));
    GPIOB->CRL |= MODE_INPUT          << (6 * 4);
    GPIOB->CRL |= CONF_INPUT_FLOATING << (6 * 4 + 2);

    // 3. 定时器配置
    
    // 3. 时基部分
    // 3.1 预分频值 71，得到1MHz
    TIM4->PSC = 71;

    // 3.2 重装载值，65535，每隔 65.535 ms 溢出一次，尽量在一个周期内不要产生溢出
    TIM4->ARR = 65535;

    // 3.3 计数方向
    TIM4->CR1 &= ~TIM_CR1_DIR;

    TIM4->EGR |= TIM_EGR_UG;
    TIM4->SR  &= ~TIM_SR_UIF;

    // 4. 输入通道部分

    // 4.1 对于通道1，配置TI1的输入选择
    TIM4->CR2 &= ~TIM_CR2_TI1S;
    
    // 4.2 输入滤波器
    TIM4->CCMR1 &= ~TIM_CCMR1_IC1F;
    
    // 4.3 配置极性：上升沿触发
    TIM4->CCER &= ~TIM_CCER_CC1P;
    
    // 4.4 选择通道1的输入映射为 TI1：CC1S - 01
    TIM4->CCMR1 &= ~TIM_CCMR1_CC1S_1;
    TIM4->CCMR1 |= TIM_CCMR1_CC1S_0;
    
    // 4.5 预分频器（不分频）
    TIM4->CCMR1 &= ~TIM_CCMR1_IC1PSC;
    
    // 4.6 通道1输入捕获使能
    TIM4->CCER |= TIM_CCER_CC1E;
    
    // 4.7 开启捕获中断使能
    TIM4->DIER |= TIM_DIER_CC1IE;
    
    // 5. NVIC配置
    NVIC_SetPriorityGrouping(3);
    NVIC_SetPriority(TIM4_IRQn, 3);
    NVIC_EnableIRQ(TIM4_IRQn);
}

// 将定时器的开关包装成函数
void TIM4_Start(void)
{
    TIM4->CR1 |= TIM_CR1_CEN;
}

void TIM4_Stop(void)
{
    TIM4->CR1 &= ~TIM_CR1_CEN;
}

void TIM4_IRQHandler(void)
{
    if (TIM4->SR & TIM_SR_CC1IF)
    {
        // 清除中断标志位
        TIM4->SR &= ~TIM_SR_CC1IF;

        // 直接清零计数器
        TIM4->CNT = 0;
    }
}

// cycle单位为us，返回周期单位为ms
double TIM4_GetPWMCycle(void)
{
    return TIM4->CCR1 / 1000.0;
}

double TIM4_GetPWMFreq(void)
{
    return 1000000.0 / TIM4->CCR1;
}

uint16_t TIM4_getCCR(void)
{
    return TIM4->CCR1;
}





